package device

import (
	"errors"
	"fmt"
	"net"
	"time"

	"gitee.com/yanwc/ebike-xiaoan-device/device"
	"gitee.com/yanwc/ebike-xiaoan-device/internal/codec"
	"gitee.com/yanwc/ebike-xiaoan-device/internal/field"
)

// 中控设备
type Device struct {
	Conn              net.Conn
	Imei              field.IMEI // Imei
	Imsi              field.IMSI // Imsi
	DeviceType        field.DeviceType
	FirmwareVersion   field.FirmwareVersion // 固件版本
	BeatHeartInterval time.Duration         // 心跳频率
	CommandCache      device.CommandCache
}

// 新建中控
func NewDevice(endpoint string, imei field.IMEI, imsi field.IMSI, version field.FirmwareVersion, opts ...DeviceOptions) (d *Device, err error) {
	d = &Device{
		Imei:              imei,    // 设备的IMEI号
		Imsi:              imsi,    // 卡的IMSI号
		FirmwareVersion:   version, // 固件版本号 Major.Minor.Patch.XXXX
		BeatHeartInterval: time.Second,
		CommandCache:      *device.NewCommandCache(),
		DeviceType:        field.HPKICKSTAND,
	}

	for _, opt := range opts {
		opt(d)
	}

	c, err := net.Dial("tcp", endpoint)
	if err != nil {
		return
	}

	d.Conn = c
	return
}

// 设备登录
func (d *Device) Login() error {
	respData := make(chan []byte)
	no, err := d.CommandCache.GenerateMsgNo(0, respData)
	if err != nil {
		return err
	}

	f := codec.NewFrame(field.LoginCommandWord, no)
	out := codec.WrapPacket(f,
		d.FirmwareVersion.Raw().Slice(),
		d.DeviceType.Raw().Slice(),
		d.Imei.Raw().Slice(),
		d.Imei.Raw().Slice())
	fmt.Printf("%#v\n", out)
	num, err := d.Conn.Write(out)
	if err != nil {
		return err
	}
	if num != len(out) {
		return errors.New("登录失败")
	}

	return nil
}

type DeviceOptions func(*Device)

func WithBeatHeartIntervalOption(interval time.Duration) DeviceOptions {
	return func(d *Device) {
		d.BeatHeartInterval = interval
	}
}
